package dai.samples.mongodb.service.impl;

import dai.samples.mongodb.bean.BucketVo;
import dai.samples.mongodb.bean.GroupVo;
import dai.samples.mongodb.entity.Order;
import dai.samples.mongodb.service.AggregationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.*;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * 聚合管道相关例子
 */
@Service
public class AggregationServiceImpl implements AggregationService {


    @Autowired
    MongoTemplate mongoTemplate;

    /**
     * 使用bucket聚合管道的例子
     * @return
     */
    @Override
    public List<BucketVo> getAggBucket() {

        BucketOperation bucketOperation =
            // 分组的字段
            Aggregation.bucket("type")
                // 根据范围进行分组
                .withBoundaries(0,1,2,3)
                // 默认分组
                .withDefaultBucket("other")
                // 求总
                .andOutput("_id").count().as("count")
                // 求和
                .andOutput("totalProduct").sum().as("sum")
                // 求平均
                .andOutput("totalMoney").avg().as("avg");
        TypedAggregation<Order> newAggregation =
            Aggregation.newAggregation(Order.class, bucketOperation);

        AggregationResults<BucketVo> noRepeatDataInfoVos2 =
            mongoTemplate.aggregate(newAggregation, BucketVo.class);
        return noRepeatDataInfoVos2.getMappedResults();
    }

    @Override
    public List<GroupVo> getAggGroup() {
        // 重排的
        GroupOperation noRepeatGroup = Aggregation.group( "userId","type")
            .count().as("num")
            .sum("totalProduct").as("count");
        TypedAggregation<Order> noRepeatAggregation =
            Aggregation.newAggregation(Order.class,noRepeatGroup);
        AggregationResults<GroupVo> noRepeatDataInfoVos = mongoTemplate.aggregate(noRepeatAggregation, GroupVo.class);
        List<GroupVo> noRepeatDataList = noRepeatDataInfoVos.getMappedResults();
        return noRepeatDataList;
    }

    /**
     * 定义返回字段名字的例子
     * @return
     */
    @Override
    public List<GroupVo> getAggProject() {

        // 重排的
        GroupOperation noRepeatGroup = Aggregation.group( "userId","type")
            .count().as("num")
            .sum("totalProduct").as("count");
        ProjectionOperation project = Aggregation.project("userId","type")
            .andInclude("num");

        TypedAggregation<Order> noRepeatAggregation =
            Aggregation.newAggregation(Order.class,noRepeatGroup,project);
        AggregationResults<GroupVo> noRepeatDataInfoVos = mongoTemplate.aggregate(noRepeatAggregation, GroupVo.class);
        List<GroupVo> noRepeatDataList = noRepeatDataInfoVos.getMappedResults();
        return noRepeatDataList;
    }

    /**
     * 拆分为指定组的例子bucketAuto
     * @return
     */
    @Override
    public List<BucketVo> getAggBucketAuto() {
            // 分组的字段
        BucketAutoOperation autoOperation = Aggregation.bucketAuto("type", 2)
            // 求总
            .andOutput("_id").count().as("count")
            // 求和
            .andOutput("totalProduct").sum().as("sum")
            // 求平均
            .andOutput("totalMoney").avg().as("avg");
        TypedAggregation<Order> newAggregation =
            Aggregation.newAggregation(Order.class, autoOperation);

        AggregationResults<BucketVo> noRepeatDataInfoVos2 =
            mongoTemplate.aggregate(newAggregation, BucketVo.class);
        return noRepeatDataInfoVos2.getMappedResults();
    }

    /**
     * 分组去重的例子
     * @return
     */
    @Override
    public List<GroupVo> getAggGroupDeDuplication() {
        // 根据用户id和type进行分组
        GroupOperation operation1 = Aggregation.group( "userId","type");
        // 对上面的结果再次分组可以获得userId相同的type数据
        GroupOperation operation2 = Aggregation.group("userId").count().as("count");

        TypedAggregation<Order> noRepeatAggregation =
            Aggregation.newAggregation(Order.class,operation1,operation2);
        AggregationResults<GroupVo> noRepeatDataInfoVos = mongoTemplate.aggregate(noRepeatAggregation, GroupVo.class);
        List<GroupVo> noRepeatDataList = noRepeatDataInfoVos.getMappedResults();
        return noRepeatDataList;
    }
}
